﻿using Framework.Common;
using System;
using System.Collections.Generic;

namespace Framework
{
    /// <summary>
    /// 模块管理器
    /// </summary>
    public class ModuleManager
    {
        /// <summary>
        /// 模块集合
        /// </summary>
        private LinkedList<IModule> m_Modules = null;

        /// <summary>
        /// 模块管理器构造函数
        /// </summary>
        public ModuleManager()
        {
            m_Modules = new LinkedList<IModule>();
        }
        /// <summary>
        /// 获得指定类型的模块
        /// </summary>
        /// <typeparam name="T">模块类型</typeparam>
        /// <returns>获得的模块</returns>
        public T GetModule<T>()
        {
            string typeFullName = typeof(T).FullName;
            int index = typeFullName.LastIndexOf('.');
            Type moduleType = Type.GetType(typeFullName.Remove(index + 1, 1));
            LinkedListNode<IModule> currentNode = m_Modules.First;
            while(currentNode != null)
            {
                if (moduleType == currentNode.Value.GetType())
                    return (T)currentNode.Value;
                currentNode = currentNode.Next;
            }
            return default(T);
        }
        /// <summary>
        /// 添加指定类型的模块
        /// </summary>
        /// <typeparam name="T">模块类型</typeparam>
        /// <returns>添加的模块实例</returns>
        public T AddModule<T>()
        {
            T module = GetModule<T>();
            if (module == null)
            {
                string interfaceName = typeof(T).FullName;
                int index = interfaceName.LastIndexOf('.');
                Type moduleType = Type.GetType(interfaceName.Remove(index + 1, 1));
                IModule tempModule = (IModule)Activator.CreateInstance(moduleType);
                if(tempModule == null)
                {
                    throw new FrameworkException("Create module failed");
                }
                tempModule.Init();
                LinkedListNode<IModule> current = m_Modules.First;
                while(current != null)
                {
                    if (tempModule.Priority > current.Value.Priority)
                        break;
                    current = current.Next;
                }
                if (current != null)
                    m_Modules.AddAfter(current, tempModule);
                else
                    m_Modules.AddLast(tempModule);
                module = (T)tempModule;
            }
            return module;
        }
        /// <summary>
        /// 是否包含指定类型的模块
        /// </summary>
        /// <typeparam name="T">模块类型</typeparam>
        /// <returns>是否包含指定类型的模块</returns>
        public bool HasModule<T>()
        {
            string typeFullName = typeof(T).FullName;
            int index = typeFullName.LastIndexOf('.');
            Type moduleType = Type.GetType(typeFullName.Remove(index + 1, 1));
            LinkedListNode<IModule> current = m_Modules.First;
            while(current != null)
            {
                if (moduleType == current.Value.GetType())
                    return true;
                current = current.Next;
            }
            return false;
        }
        /// <summary>
        /// 移除指定类型的模块
        /// </summary>
        /// <typeparam name="T">模块类型</typeparam>
        public void RemoveModule<T>()
        {
            string typeFullName = typeof(T).FullName;
            int index = typeFullName.LastIndexOf('.');
            Type moduleType = Type.GetType(typeFullName.Remove(index + 1, 1));
            LinkedListNode<IModule> current = m_Modules.First;
            while (current != null)
            {
                if (moduleType == current.Value.GetType())
                {
                    current.Value.Destroy();
                    m_Modules.Remove(current);
                    return;
                }
                current = current.Next;
            }
        }
        /// <summary>
        /// 模块轮询接口
        /// </summary>
        /// <param name="frameTime">逻辑一帧时间</param>
        /// <param name="realTime">实际一帧时间</param>
        public void Update(float frameTime, float realTime)
        {
            LinkedListNode<IModule> current = m_Modules.First;
            while(current != null)
            {
                current.Value.Update(frameTime, realTime);
                current = current.Next;
            }
        }
        /// <summary>
        /// 移除所有的模块
        /// </summary>
        public void RemoveAllModule()
        {
            while(m_Modules.Count > 0)
            {
                m_Modules.First.Value.Destroy();
                m_Modules.RemoveFirst();
            }
        }
        /// <summary>
        /// 重置所有模块
        /// </summary>
        public void Reset()
        {
            LinkedListNode<IModule> current = m_Modules.First;
            while(current != null)
            {
                current.Value.Reset();
                current = current.Next;
            }
        }
    }
}
